package table

//坐席相关逻辑，庄家、大富豪、神算子
import (
	"lol.com/feb214-game/nest.git/log"
	"sort"
	"sync/atomic"
	"talent.com/cube/common/cxt"
	"talent.com/cube/common/msg"
	"talent.com/cube/conf"
	"talent.com/cube/conf/g"
)

//生成系统坐庄信息
func genSysBanker(gameType int32) *msg.UserST {
	var credit int64
	credit = conf.GetSysMaxPay(gameType)
	return &msg.UserST{
		ID:     0,
		Credit: credit, //其他游戏没有最大赔付金额限制
	}
}

//更新坐席settle阶段
func updateTopPlayerSettle(tc *cxt.TableContext) *msg.TopPlayerST {
	log.Info("settle after update topInfo")
	//结算时候不换top，只把当前BestUser的连胜效果返回给客户端
	isBestDown := false
	bigWinCount := int32(0)
	if tc.BestUser != nil {
		bestUser := tc.Players.GetPlayer(tc.BestUser.ID)
		if bestUser != nil {
			if bestUser.Award > tc.CostCache[tc.BestUser.ID] {
				atomic.AddInt32(&bestUser.BigWinCount, 1)
			} else if tc.CostCache[tc.BestUser.ID] > 0 {
				if bestUser.Award < tc.CostCache[tc.BestUser.ID] {
					if atomic.LoadInt32(&bestUser.BigWinCount) >= 3 {
						isBestDown = true
					}
					atomic.StoreInt32(&bestUser.BigWinCount, 0)
				}
			}
			bigWinCount = bestUser.BigWinCount
		}
	}
	return &msg.TopPlayerST{
		BestUser:         tc.BestUser,
		RichUsers:        tc.RichUsers,
		BestUserWinCount: int64(bigWinCount),
		BestUserWinRate:  float32(0),
		IsBestDown:       isBestDown,
	}
}

//更新坐席
func updateTopPlayer(tc *cxt.TableContext) {
	//开局更新坐席，只在第一轮进行一次更新
	lastBestUer := tc.BestUser
	_, winRate := updateBestUser(tc)
	if lastBestUer != nil && tc.BestUser != nil && lastBestUer.ID != tc.BestUser.ID {
		bestUser := tc.Players.GetPlayer(tc.BestUser.ID)
		atomic.StoreInt32(&bestUser.BigWinCount, 0)
	}
	betPairs, bestBet := updateRichUsers(tc)
	snap := make([]*cxt.TopUserRO, 0, g.TopBetCount+1) //额外有个神算子
	genRO := func(userId uint64, bet int64) *cxt.TopUserRO {
		u := tc.Players.GetPlayer(userId)
		return &cxt.TopUserRO{
			ID:        userId,
			UserName:  u.UserName,
			Avatar:    u.Avatar,
			Gender:    u.Gender,
			Credit:    float64(u.Credit) / g.CoinRate,
			BetAmount: float64(bet) / g.CoinRate,
			WinCount:  int(u.BigWinCount),
		}
	}
	if tc.BestUser != nil {
		snap = append(snap, genRO(tc.BestUser.ID, bestBet))
	} else {
		snap = append(snap, nil)
	}
	var count int
	for _, pair := range betPairs {
		if count >= g.TopBetCount {
			break
		}
		snap = append(snap, genRO(pair.UserId, pair.Amount))
		count++
	}
	tc.TopUserSnap = snap
	var BestUserWinCount int64
	if len(snap) != 0 {
		BestUserWinCount = int64(snap[0].WinCount)
	}
	log.Info("user_id: %v, count: %v winRate: %v", tc.BestUser.ID, BestUserWinCount, winRate)
	broadcast(tc, &msg.TopPlayerST{
		BestUser:         tc.BestUser,
		RichUsers:        tc.RichUsers,
		BestUserWinCount: BestUserWinCount,
		BestUserWinRate:  float32(winRate),
	})
}

type userAmountPair struct {
	UserId uint64
	Amount int64
}

//更新大富豪, 返回所有用户的下注排名和神算子的下注
func updateRichUsers(tc *cxt.TableContext) ([]*userAmountPair, int64) {
	tc.RichUsers = nil
	if tc.HistoryBetters == nil || tc.HistoryBetters.Len() == 0 {
		return []*userAmountPair{}, 0
	}
	var (
		uid     uint64
		amount  int64
		bestBet int64

		allBetters = make(map[uint64]int64, tc.HistoryBetters.Len())
	)
	for better := tc.HistoryBetters.Front(); better != nil; better = better.Next() {
		record := better.Value.(map[uint64]int64)
		for uid, amount = range record {
			allBetters[uid] += amount
		}
	}
	cas := make([]*userAmountPair, 0, len(allBetters))
	for uid, amount := range allBetters {
		//仅取在线用户
		if tc.Players.GetPlayer(uid) == nil || atomic.LoadInt32(&tc.Players.GetPlayer(uid).Disconnect) == 1 {
			continue
		}
		//不能是神算子
		if tc.BestUser != nil && tc.BestUser.ID == uid {
			bestBet = amount
			continue
		}
		cas = append(cas, &userAmountPair{
			UserId: uid,
			Amount: amount,
		})
	}
	sort.Slice(cas, func(i, j int) bool {
		return cas[i].Amount > cas[j].Amount //下注越多越小，所以最前面的几个是大富豪
	})
	if len(cas) == 0 {
		return cas, bestBet
	}
	tops := cas
	if len(tops) > g.RichUserCount {
		tops = tops[:g.RichUserCount]
	}
	tc.RichUsers = make([]*msg.UserST, 0, len(tops))
	for _, top := range tops {
		tc.RichUsers = append(tc.RichUsers, tc.Players.GetPlayer(top.UserId).UserST)
	}
	return cas, bestBet
}

//更新神算子，返回所有用户的赢局记录
func updateBestUser(tc *cxt.TableContext) (map[uint64]int, float64) {
	if tc.BestUser != nil {
		lastBestUser := tc.BestUser.ID
		log.Info("lastBestUser: %v", lastBestUser)
	}
	tc.BestUser = nil
	counter := make(map[uint64]int)
	if tc.HistoryWinners == nil || tc.HistoryWinners.Len() == 0 {
		return counter, 0
	}
	var (
		winnerIds []uint64
		winnerId  uint64
		bestCount int
		bestId    uint64
	)
	for elem := tc.HistoryWinners.Front(); elem != nil; elem = elem.Next() {
		winnerIds = elem.Value.([]uint64)
		for _, winnerId = range winnerIds {
			counter[winnerId] += 1
			//在线且胜率最高
			if tc.Players.GetPlayer(winnerId) != nil && counter[winnerId] > bestCount {
				bestId = winnerId
				bestCount = counter[winnerId]
			}
		}
	}
	var winRate = float64(bestCount) / float64(g.TopTermCount)
	log.Info("win rate: %v", winRate)
	if bestId != 0 {
		tc.BestUser = tc.Players.GetPlayer(bestId).UserST
	}
	return counter, winRate
}

//下一个庄家
func getNextBanker(tc *cxt.TableContext) (banker *msg.UserST, reElection bool) {
	////队列里只有系统，则下一局仍然是系统
	//if !g.IsBankerGame(tc.GameType) || (len(tc.BankerList) == 1 && tc.BankerList[0].ID == 0) {
	//	banker = tc.BankerList[0]
	//	banker.Award = 0
	//
	//	banker.Credit = conf.GetSysMaxPay(tc.GameType)
	//	return
	//}
	//var (
	//	index   int
	//	current *msg.UserST
	//	left    int
	//
	//	rc = conf.RoomConfig(tc.GameType, tc.Kind)
	//)
	//for index = 0; index < len(tc.BankerList); index++ {
	//	current = tc.BankerList[index]
	//	//系统坐庄或者用户断线
	//	if current.ID == 0 || tc.Players[current.ID] == nil {
	//		continue
	//	}
	//	//<0是主动下庄，=0是坐庄次数用完被动下庄
	//	if left = tc.Players[current.ID].LeftBankerTimes; left <= 0 {
	//		if left == 0 {
	//			pushUser(current.ID, &proto.ErrorST{
	//				Status: proto.STATUS_CUBE_OFF_BANKER_FOR_COUNT,
	//			})
	//		}
	//		continue
	//	}
	//	if current.Credit < rc.BankerLimit {
	//		pushUser(current.ID, &proto.ErrorST{
	//			Status: proto.STATUS_CUBE_OFF_BANKER_FOR_CREDIT,
	//		})
	//		continue
	//	}
	//	break
	//}
	////没有合适的，仍然是系统上庄
	//if index == len(tc.BankerList) {
	//	tc.BankerList = []*msg.UserST{
	//		genSysBanker(tc.GameType),
	//	}
	//	syncBankerList(tc)
	//} else if index != 0 {
	//	tc.BankerList = tc.BankerList[index:]
	//	syncBankerList(tc)
	//}
	//banker = tc.BankerList[0]
	//if banker.ID != 0 {
	//	tc.Players[banker.ID].LeftBankerTimes--
	//	reElection = index == 0
	//}
	return
}
